#!/usr/bin/env python
# encoding: utf-8

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from RayGraphWidget import RayCanvasWidget

from ui.scan import Ui_Dialog as scanDialog
from win32api import GetSystemMetrics

from pyqtgraph.opengl import GLViewWidget
import pyqtgraph.opengl as gl
import pyqtgraph as pg
import numpy as np
import os

class ScanResultWidget(GLViewWidget):
    def __init__(self):
        super(ScanResultWidget, self).__init__()
        self.opts['distance'] = 40
        self.gx = gl.GLGridItem()
        self.gx.rotate(90, 0, 1, 0)
        self.gx.translate(-10, 0, 0)
        self.addItem(self.gx)
        self.gy = gl.GLGridItem()
        self.gy.rotate(90, 1, 0, 0)
        self.gy.translate(0, -10, 0)
        self.addItem(self.gy)
        self.gz = gl.GLGridItem()
        self.gz.translate(0, 0, -10)
        self.addItem(self.gz)
        self.setScale(40,40,100)
        self.drawDirectionLine()

    def setScale(self, size_x, size_y, size_z):
        # axis range ---> x,y,z
        self.x_min = -20
        self.x_max = 20
        self.y_min = -20
        self.y_max = 20
        self.z_min = -20
        self.z_max = 20
        # set real range
        self.x_range = size_x
        self.y_range = size_y
        self.z_range = size_z
        # get transform scale
        self.x_scale = (self.x_max-self.x_min)/self.x_range
        self.y_scale = (self.y_max-self.y_min)/self.y_range
        self.z_scale = (self.z_max-self.z_min)/self.z_range

    def drawDirectionLine(self):
        # draw direction A->B
        self.vLine = gl.GLLinePlotItem(pos=np.array([[self.x_min/2,0,self.z_min/2],[self.x_max/2,0,self.z_min/2]]), color=pg.glColor(0,250,255), width=1, antialias=True)
        self.addItem(self.vLine)
        # draw direction G->T
        self.hLine = gl.GLLinePlotItem(pos=np.array([[0,self.y_min/2,self.z_min/2],[0,self.y_max/2,self.z_min/2]]), color=pg.glColor(250,0,255), width=1, antialias=True)
        self.addItem(self.hLine)
        # draw direction Z
        self.zLine = gl.GLLinePlotItem(pos=np.array([[0,self.y_min/2,self.z_min/2],[0,self.y_min/2,self.z_max/2]]), color=pg.glColor(250,0,55), width=1, antialias=True)
        self.addItem(self.zLine)

    def paintGL(self, *args, **kwds):
        GLViewWidget.paintGL(self, *args, **kwds)
        self.qglColor(Qt.white)
        for i in range(self.x_min,self.x_max+1):
            if i%2 == 0:
                # x axis
                self.renderText(i/2, self.y_max/2+2, self.z_min/2, str(int(i/self.x_scale)))
                # y axis
                self.renderText(self.x_max/2+2, i/2, self.z_min/2, str(int(i/self.y_scale)))
                # z axis
                self.renderText(self.x_min/2, self.y_max/2+1, i/2, str(int(i/self.z_scale)+self.z_range/2))
        self.renderText(0, 0, self.z_max/2+5, '平面扫描结果实时显示')
        self.qglColor(Qt.blue)
        self.renderText(self.x_min/2, self.y_max/2, 12, '百分比深度剂量(%)')
        self.renderText(0, self.y_max/2+5, self.z_min/2, 'x(mm)')
        self.renderText(self.x_max/2+5, 0, self.z_min/2, 'y(mm)')
        self.qglColor(Qt.green)
        self.renderText(self.x_min/2, 0, self.z_min/2, 'A')
        self.renderText(self.x_max/2, 0, self.z_min/2, 'B')
        self.renderText(0, self.y_min/2, self.z_min/2, 'G')
        self.renderText(0, self.y_max/2, self.z_min/2, 'T')

    def axisToGL(self,x,y,z):
        x = [t*self.x_scale/2 for t in x]
        y = [t*self.y_scale/2 for t in y]
        z = [t*self.z_scale/2-self.z_max/2 for t in z]
        return x,y,z

    def updateSurface(self, x, y, z, size):
        self.setScale(int(size)*10*2,int(size)*10*2,100)
        x,y,z = self.axisToGL(x,y,z)
        pos = np.array([[a,b,c] for a,b,c in zip(x,y,z)])
        self.items = []
        self.addItem(self.gx)
        self.addItem(self.gy)
        self.addItem(self.gz)
        self.addItem(self.hLine)
        self.addItem(self.vLine)
        self.addItem(self.zLine)
        sp = gl.GLScatterPlotItem(pos=pos, size=0.1, color=(0.0, 1.0, 0.0, 1), pxMode=False)
        self.addItem(sp)

class ScanDialog(QDialog, scanDialog):
    def __init__(self,parent=None):
        super(QDialog, self).__init__(parent)
        self.setupUi(self)
        # if SKIN == 'style_Dark':
            # self.setStyleSheet(PyQt5_stylesheets.load_stylesheet_pyqt5(style="style_Dark"))
        # if SKIN == 'style_Default':
            # pass
        self.setWindowTitle('扫描任务设置')
        w = GetSystemMetrics(0)/2
        h = GetSystemMetrics(1)/1.2
        self.setFixedSize(w,h)
        self.angle = 0
        # 扫描示意图
        self.rayCanvasWidget = RayCanvasWidget()
        self.verticalLayout_chart.addWidget(self.rayCanvasWidget)
        # 信号绑定
        self.lineEdit_step1.setValidator(QRegExpValidator(QRegExp("[0-9]+$"), self.lineEdit_step1))
        self.lineEdit_step1.textChanged.connect(self.updateRay)
        self.lineEdit_step2.setValidator(QRegExpValidator(QRegExp("[0-9]+$"), self.lineEdit_step2))
        self.lineEdit_step2.textChanged.connect(self.updateRay)
        self.lineEdit_deepth.setValidator(QRegExpValidator(QRegExp("[0-9]+$"), self.lineEdit_deepth))
        self.lineEdit_deepth.textChanged.connect(self.updateRay)
        self.lineEdit_raySize_x.setValidator(QRegExpValidator(QRegExp("[0-9]+$"), self.lineEdit_raySize_x))
        self.lineEdit_raySize_y.setValidator(QRegExpValidator(QRegExp("[0-9]+$"), self.lineEdit_raySize_y))
        self.lineEdit_raySize_x.textChanged.connect(self.updateRay)
        self.lineEdit_raySize_y.textChanged.connect(self.updateRay)
        self.comboBox_direction.currentIndexChanged.connect(self.updateRay)
        self.comboBox_rayType.currentIndexChanged.connect(self.updateRay)
        self.comboBox_power.currentIndexChanged.connect(self.updateRay)
        self.radioButton_1.clicked.connect(self.updateRay)
        self.radioButton_2.clicked.connect(self.updateRay)
        self.radioButton_3.clicked.connect(self.updateRay)
        self.radioButton_4.clicked.connect(self.updateRay)

        self.btn_ok.clicked.connect(self.accept)
        self.btn_cancel.clicked.connect(self.reject)
        # 限制输入框只能输入数字
        self.raySize = 10
        self.updateRay()

    def raytype_changed(self):
        """射线类型变化，能量单位跟着变化"""
        if self.comboBox_rayType.currentText() == "电子":
            self.label_power.setText("能量(MeV)")
        if self.comboBox_rayType.currentText() == "光子":
            self.label_power.setText("能量(MV)")

    def styleChaned(self):
        pixmap = None
        if self.radioButton_1.isChecked():
            self.angle = 40
            pixmap = QPixmap(r"%s/ui/images_rc/xyz-1.png"%os.getcwd())
        if self.radioButton_2.isChecked():
            self.angle = 130
            pixmap = QPixmap(r"%s/ui/images_rc/xyz-2.png"%os.getcwd())
        if self.radioButton_3.isChecked():
            self.angle = 220
            pixmap = QPixmap(r"%s/ui/images_rc/xyz-3.png"%os.getcwd())
        if self.radioButton_4.isChecked():
            self.angle = 310
            pixmap = QPixmap(r"%s/ui/images_rc/xyz-4.png"%os.getcwd())
        pixmap.scaled(self.label_style.size(), Qt.KeepAspectRatio)
        self.label_style.setScaledContents(True)
        self.label_style.setPixmap(pixmap)

    def updateRay(self):
        ssd           = (self.lineEdit_SSD.text())
        raySize_x     = (self.lineEdit_raySize_x.text())
        raySize_y     = (self.lineEdit_raySize_y.text())
        step_x = (self.lineEdit_step1.text())
        step_y = (self.lineEdit_step2.text())
        deepth = (self.lineEdit_deepth.text())
        if ssd and raySize_x and raySize_y and step_x and step_y:
            ssd           = float(ssd)
            raySize_x     = float(raySize_x)
            raySize_y     = float(raySize_y)
            step_x= float(step_x)
            step_y= float(step_y)
            deepth= float(deepth)
            direction = self.comboBox_direction.currentText()
            self.styleChaned()
            self.road = self.getRoad(raySize_x,raySize_y,step_x,step_y,deepth,direction)
            self.label_number.setText('扫描点数:%s'%len(self.road))
            self.rayCanvasWidget.updateItems(
                                        angle=self.angle,
                                        ssd=-ssd,
                                        raySize_x=raySize_x,
                                        raySize_y=raySize_y,
                                        deepth=deepth,road=self.road)

    def getRoad(self,raysize_x,raysize_y,step_x,step_y,deepth,direction):
        s_x = raysize_x*10
        s_y = raysize_y*10
        x = np.arange(-s_x/2,s_x/2+1,step_x)
        y = np.arange(-s_y/2,s_y/2+1,step_y)
        res_x = int(s_x) % int(step_x)
        res_y = int(s_y) % int(step_y)
        if not res_x == 0:
            x = np.append(x, s_x/2)
        if not res_y == 0:
            y = np.append(y, s_y/2)
        if direction == 'A->B':
            x, y = np.meshgrid(x, y)    # x-y 平面的网格
        if direction == 'G->T':
            y, x = np.meshgrid(x, y)    # x-y 平面的网格
        road = []
        i_len = len(x)
        j_len = len(x[0])
        for i in range(0,i_len):
            for j in range(0,j_len):
                if i%2 == 0:
                    road.append([x[i][j],y[i][j],deepth])
                else:
                    road.append([x[i][j_len-1-j],y[i][j_len-1-j],deepth])
        return road

    def load_config(self, conf):
        num = re.compile('^([0-9]+).*$') #regex for num
        self.road = conf['road']
        self.lineEdit_deepth.setText(num.match(conf['deepth']).group(1))
        self.comboBox_rayType.setCurrentIndex(conf['rayTypeNum'])
        self.lineEdit_power.setText(num.match(conf['power']).group(1))
        self.lineEdit_SSD.setText(num.match(conf['ssd']).group(1))
        self.lineEdit_raySize_x.setText(num.match(conf['raySizeX']).group(1))
        self.lineEdit_raySize_y.setText(num.match(conf['raySizeY']).group(1))
        self.comboBox_direction.setCurrentIndex(conf['directionNum'])
        self.lineEdit_step1.setText(str(int(conf['step_x'])))
        self.lineEdit_step2.setText(str(int(conf['step_y'])))
        self.updateRay()

    def accept(self):
        self.conf = {
            'type':'SCAN',
            'road':self.road,
            'deepth':self.lineEdit_deepth.text()+'mm',
            'rayType':self.comboBox_rayType.currentText(),
            'rayTypeNum':self.comboBox_rayType.currentIndex(),
            'power':self.lineEdit_power.text()+'MeV',
            'ssd':self.lineEdit_SSD.text()+'cm',
            'raySizeX':self.lineEdit_raySize_x.text()+'cm',
            'raySizeY':self.lineEdit_raySize_y.text()+'cm',
            'step_x':self.lineEdit_step1.text(),
            'step_y':self.lineEdit_step2.text(),
            'direction':self.comboBox_direction.currentText(),
            'directionNum':self.comboBox_direction.currentIndex(),
        }
        QDialog.accept(self)

    def reject(self):
        QDialog.reject(self)

if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    win = ScanDialog()
    win.show()
    app.exec_()


